﻿using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace MouseAndCat.Model
{
    public class Messenger
    {
        public delegate void MouseLeaveDelegate(short y);
        public event MouseLeaveDelegate MouseLeave;

#if DEBUG
        private long _lastReport = DateTime.UtcNow.Ticks;
        private const long OneSecondInTicks = 10000000;
        private const long ReportInterval = OneSecondInTicks / 2;
#endif

        private UdpClient _udpClient = new UdpClient();
        private readonly object _lockForListen = new object();
        private bool _listening = false;
        private IPEndPoint _clientEndPoint;

        public Messenger(IPAddress ip, int port)
        {
            _clientEndPoint = new IPEndPoint(ip, port);
        }

        public void Send(Message message)
        {
            if (DateTime.UtcNow.Ticks - _lastReport > ReportInterval)
            {
                System.Diagnostics.Debug.WriteLine(String.Format("Sending message: {0} to: {1}:{2}", message, _clientEndPoint.Address, _clientEndPoint.Port));
                _lastReport = DateTime.UtcNow.Ticks;
            }

            byte[] data = message.Bytes;

            /*StringBuilder bytesString = new StringBuilder(255);
            foreach (byte b in data)
               bytesString.AppendFormat("{0} ", b);

            System.Diagnostics. Debug.WriteLine(bytesString);*/
            _udpClient.Send(data, data.Length, _clientEndPoint);
        }

        public void ListenOnce()
        {
            lock (_lockForListen)
            {
                if (_listening)
                {
                    Debug.WriteLine("Already listening!!");
                    return;
                }
            }
            Thread listenThread = new Thread(DoListenOnce);
            listenThread.Start();
        }

        private void DoListenOnce()
        {
            UdpClient udpServer = new UdpClient(_clientEndPoint.Port);
            IPEndPoint serverEndpoint = new IPEndPoint(_clientEndPoint.Address, _clientEndPoint.Port);
            Debug.WriteLine("Listening on " + serverEndpoint.ToString());

            lock (_lockForListen)
                _listening = true;

            byte[] data = udpServer.Receive(ref serverEndpoint);

            StringBuilder bytesString = new StringBuilder(255);
            foreach (byte b in data)
               bytesString.AppendFormat("{0} ", b);

            Debug.WriteLine("Received bytes on UDP: " + bytesString);

            if ((Event)data[0] == Event.MouseLeave)
            {
                short y = data[1];
                MouseLeave(y);
            }

            udpServer.Close();
            udpServer = null;

            lock (_lockForListen)
                _listening = false;
        }
    }
}
